#ifndef CAFFEINE_ENTITY_IENTITY_HPP
#define CAFFEINE_ENTITY_IENTITY_HPP

#include "Common.hpp"
#include "Math/Vector.hpp"
#include "Utility/Creator.hpp"
#include "Utility/EntityFactory.hpp"

#include <queue>
#include <string>
#include <vector>

namespace Graphics
{
	class ISprite;
}

namespace Physics
{
	class IBody;
}

namespace Entity
{
	class IEntity
	{
		friend class Utility::EntityFactory;
	public:
		IEntity( void );
		virtual ~IEntity( void );

		virtual void Think( const float frameTime );
		virtual void Draw( void );
		virtual void Remove( void );

		std::string GetClass( void ) const;

		virtual Graphics::ISprite *GetSprite( void );
		virtual Physics::IBody *GetPhysicsBody( void );

		virtual float GetAngle( void ) const;
		virtual void SetAngle( const float ang );

		virtual Math::Vectorf GetPosition( void ) const;
		virtual void SetPosition( const Math::Vectorf &pos );

		virtual Math::Vectorf GetSize( void ) const;
		virtual void SetSize( const Math::Vectorf &vec );

		virtual float GetAngularVelocity( void ) const;
		virtual void SetAngularVelocity( const float vel );

		virtual Math::Vectorf GetLinearVelocity( void ) const;
		virtual void SetLinearVelocity( const Math::Vectorf &vel );

		static unsigned Number( void );
		static IEntity *GetByID( const unsigned getID );
		static void ThinkAll( const float frameTime );
	private:
		void SetClass( const std::string setClass );

		std::string className;
		unsigned id;
		std::queue< unsigned > availableIDs;

		float angle;
		Math::Vectorf position;
		Math::Vectorf size;

		float angVel;
		Math::Vectorf linVel;

		static std::vector< IEntity * > entityList;
	};
}

#endif //CAFFEINE_ENTITY_IENTITY_HPP